/*
 * @文件描述: 外部SRAM的驱动
 * @版本: 
 * @作者: 周晨阳
 * @Date: 2021-01-19 17:15:00
 * @说明
 * 此驱动的初始化函数会由系统在main函数执行前调用，所以用户不需要再次调用初始化
 */
#include "mySRAM.h"

//使用NOR/SRAM的 Bank1.sector3,地址位HADDR[27,26]=10
//对IS61LV25616/IS62WV25616,地址线范围为A0~A17
//对IS61LV51216/IS62WV51216,地址线范围为A0~A18
#define Bank1_SRAM3_ADDR ((u32)(0x68000000))

//GPIO设置专用宏定义
#define GPIO_MODE_IN 0  //普通输入模式
#define GPIO_MODE_OUT 1 //普通输出模式
#define GPIO_MODE_AF 2  //AF功能模式
#define GPIO_MODE_AIN 3 //模拟输入模式

#define GPIO_SPEED_2M 0   //GPIO速度2Mhz
#define GPIO_SPEED_25M 1  //GPIO速度25Mhz
#define GPIO_SPEED_50M 2  //GPIO速度50Mhz
#define GPIO_SPEED_100M 3 //GPIO速度100Mhz

#define GPIO_PUPD_NONE 0 //不带上下拉
#define GPIO_PUPD_PU 1   //上拉
#define GPIO_PUPD_PD 2   //下拉
#define GPIO_PUPD_RES 3  //保留

#define GPIO_OTYPE_PP 0 //推挽输出
#define GPIO_OTYPE_OD 1 //开漏输出

//GPIO引脚编号定义
#define PIN0 1 << 0
#define PIN1 1 << 1
#define PIN2 1 << 2
#define PIN3 1 << 3
#define PIN4 1 << 4
#define PIN5 1 << 5
#define PIN6 1 << 6
#define PIN7 1 << 7
#define PIN8 1 << 8
#define PIN9 1 << 9
#define PIN10 1 << 10
#define PIN11 1 << 11
#define PIN12 1 << 12
#define PIN13 1 << 13
#define PIN14 1 << 14
#define PIN15 1 << 15
void GPIO_AF_Set(GPIO_TypeDef *GPIOx, u8 BITx, u8 AFx)
{
    GPIOx->AFR[BITx >> 3] &= ~(0X0F << ((BITx & 0X07) * 4));
    GPIOx->AFR[BITx >> 3] |= (u32)AFx << ((BITx & 0X07) * 4);
}
//GPIO通用设置
//GPIOx:GPIOA~GPIOI.
//BITx:0X0000~0XFFFF,位设置,每个位代表一个IO,第0位代表Px0,第1位代表Px1,依次类推.比如0X0101,代表同时设置Px0和Px8.
//MODE:0~3;模式选择,0,输入(系统复位默认状态);1,普通输出;2,复用功能;3,模拟输入.
//OTYPE:0/1;输出类型选择,0,推挽输出;1,开漏输出.
//OSPEED:0~3;输出速度设置,0,2Mhz;1,25Mhz;2,50Mhz;3,100Mh.
//PUPD:0~3:上下拉设置,0,不带上下拉;1,上拉;2,下拉;3,保留.
//注意:在输入模式(普通输入/模拟输入)下,OTYPE和OSPEED参数无效!!
void GPIO_Set(GPIO_TypeDef *GPIOx, u32 BITx, u32 MODE, u32 OTYPE, u32 OSPEED, u32 PUPD)
{
    u32 pinpos = 0, pos = 0, curpin = 0;
    for (pinpos = 0; pinpos < 16; pinpos++)
    {
        pos = 1 << pinpos;   //一个个位检查
        curpin = BITx & pos; //检查引脚是否要设置
        if (curpin == pos)   //需要设置
        {
            GPIOx->MODER &= ~(3 << (pinpos * 2)); //先清除原来的设置
            GPIOx->MODER |= MODE << (pinpos * 2); //设置新的模式
            if ((MODE == 0X01) || (MODE == 0X02)) //如果是输出模式/复用功能模式
            {
                GPIOx->OSPEEDR &= ~(3 << (pinpos * 2));     //清除原来的设置
                GPIOx->OSPEEDR |= (OSPEED << (pinpos * 2)); //设置新的速度值
                GPIOx->OTYPER &= ~(1 << pinpos);            //清除原来的设置
                GPIOx->OTYPER |= OTYPE << pinpos;           //设置新的输出模式
            }
            GPIOx->PUPDR &= ~(3 << (pinpos * 2)); //先清除原来的设置
            GPIOx->PUPDR |= PUPD << (pinpos * 2); //设置新的上下拉
        }
    }
}
//初始化外部SRAM
void FSMC_SRAM_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef readWriteTiming;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG, ENABLE); //使能PD,PE,PF,PG时钟
    RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);                                                                       //使能FSMC时钟

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;       //复用输出
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;     //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;       //上拉
    
    //地址线
    GPIO_InitStructure.GPIO_Pin = SRAM_A0_PIN;
    GPIO_Init(SRAM_A0_PORT, &GPIO_InitStructure); //初始化

    GPIO_InitStructure.GPIO_Pin = SRAM_A1_PIN;
    GPIO_Init(SRAM_A1_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A2_PIN;
    GPIO_Init(SRAM_A2_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A3_PIN;
    GPIO_Init(SRAM_A3_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A4_PIN;
    GPIO_Init(SRAM_A4_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A5_PIN;
    GPIO_Init(SRAM_A5_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A6_PIN;
    GPIO_Init(SRAM_A6_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A7_PIN;
    GPIO_Init(SRAM_A7_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A8_PIN;
    GPIO_Init(SRAM_A8_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A9_PIN;
    GPIO_Init(SRAM_A9_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A10_PIN;
    GPIO_Init(SRAM_A10_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A11_PIN;
    GPIO_Init(SRAM_A11_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A12_PIN;
    GPIO_Init(SRAM_A12_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A13_PIN;
    GPIO_Init(SRAM_A13_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A14_PIN;
    GPIO_Init(SRAM_A14_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A15_PIN;
    GPIO_Init(SRAM_A15_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A16_PIN;
    GPIO_Init(SRAM_A16_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A17_PIN;
    GPIO_Init(SRAM_A17_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_A18_PIN;
    GPIO_Init(SRAM_A18_PORT, &GPIO_InitStructure);

    //数据线
    GPIO_InitStructure.GPIO_Pin = SRAM_D0_PIN;
    GPIO_Init(SRAM_D0_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D1_PIN;
    GPIO_Init(SRAM_D1_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D2_PIN;
    GPIO_Init(SRAM_D2_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D3_PIN;
    GPIO_Init(SRAM_D3_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D4_PIN;
    GPIO_Init(SRAM_D4_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D5_PIN;
    GPIO_Init(SRAM_D5_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D6_PIN;
    GPIO_Init(SRAM_D6_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D7_PIN;
    GPIO_Init(SRAM_D7_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D8_PIN;
    GPIO_Init(SRAM_D8_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D9_PIN;
    GPIO_Init(SRAM_D9_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D10_PIN;
    GPIO_Init(SRAM_D10_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D11_PIN;
    GPIO_Init(SRAM_D11_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D12_PIN;
    GPIO_Init(SRAM_D12_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D13_PIN;
    GPIO_Init(SRAM_D13_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D14_PIN;
    GPIO_Init(SRAM_D14_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_D15_PIN;
    GPIO_Init(SRAM_D15_PORT, &GPIO_InitStructure);

    //控制线
    GPIO_InitStructure.GPIO_Pin = SRAM_NBL0_PIN;
    GPIO_Init(SRAM_NBL0_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_NBL1_PIN;
    GPIO_Init(SRAM_NBL1_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_CS_PIN;
    GPIO_Init(SRAM_CS_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_NOE_PIN;
    GPIO_Init(SRAM_NOE_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SRAM_NWE_PIN;
    GPIO_Init(SRAM_NWE_PORT, &GPIO_InitStructure);

    //40个引脚
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); //PD0,AF12
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC); //PD1,AF12
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC); //PD15,AF12

    GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FSMC); //PE7,AF12
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC); //PE15,AF12

    GPIO_PinAFConfig(GPIOF, GPIO_PinSource0, GPIO_AF_FSMC);  //PF0,AF12
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource1, GPIO_AF_FSMC);  //PF1,AF12
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource2, GPIO_AF_FSMC);  //PF2,AF12
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource3, GPIO_AF_FSMC);  //PF3,AF12
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource4, GPIO_AF_FSMC);  //PF4,AF12
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource5, GPIO_AF_FSMC);  //PF5,AF12
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource12, GPIO_AF_FSMC); //PF12,AF12
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource13, GPIO_AF_FSMC); //PF13,AF12
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource14, GPIO_AF_FSMC); //PF14,AF12
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource15, GPIO_AF_FSMC); //PF15,AF12

    GPIO_PinAFConfig(GPIOG, GPIO_PinSource0, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource1, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource2, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource3, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource4, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource5, GPIO_AF_FSMC);
    GPIO_PinAFConfig(GPIOG, GPIO_PinSource10, GPIO_AF_FSMC);

    readWriteTiming.FSMC_AddressSetupTime = 0x00; //地址建立时间（ADDSET）为1个HCLK 1/36M=27ns
    readWriteTiming.FSMC_AddressHoldTime = 0x00;  //地址保持时间（ADDHLD）模式A未用到
    readWriteTiming.FSMC_DataSetupTime = 0x08;    ////数据保持时间（DATAST）为9个HCLK 6*9=54ns
    readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
    readWriteTiming.FSMC_CLKDivision = 0x00;
    readWriteTiming.FSMC_DataLatency = 0x00;
    readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A

    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3; //  这里我们使用NE3 ，也就对应BTCR[4],[5]。
    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
    FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;              // FSMC_MemoryType_SRAM;  //SRAM
    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;     //存储器数据宽度为16bit
    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; // FSMC_BurstAccessMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
    FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
    FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; //存储器写使能
    FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; // 读写使用相同的时序
    FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;
    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming; //读写同样时序

    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC配置

    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE); // 使能BANK1区域3

   
}

//在指定地址(WriteAddr+Bank1_SRAM3_ADDR)开始,连续写入n个字节.
//pBuffer:字节指针
//WriteAddr:要写入的地址
//n:要写入的字节数
void FSMC_SRAM_WriteBuffer(u8 *pBuffer, u32 WriteAddr, u32 n)
{
    for (; n != 0; n--)
    {
        *(vu8 *)(Bank1_SRAM3_ADDR + WriteAddr) = *pBuffer;
        WriteAddr++;
        pBuffer++;
    }
}
//在指定地址((WriteAddr+Bank1_SRAM3_ADDR))开始,连续读出n个字节.
//pBuffer:字节指针
//ReadAddr:要读出的起始地址
//n:要写入的字节数
void FSMC_SRAM_ReadBuffer(u8 *pBuffer, u32 ReadAddr, u32 n)
{
    for (; n != 0; n--)
    {
        *pBuffer++ = *(vu8 *)(Bank1_SRAM3_ADDR + ReadAddr);
        ReadAddr++;
    }
}
